package org.dicr.util.jds.gui;

import java.util.*;

import javax.swing.*;

import org.dicr.event.*;
import org.dicr.util.jds.*;

import com.borland.dx.dataset.*;

/***********************************************************************************************************************
 * <p>
 * Title: DiJaWo
 * </p>
 * <p>
 * Description: Dicr Java Utilites
 * </p>
 * <p>
 * Copyright: (C) by Dicr 2002
 * </p>
 * <p>
 * Company: Dicr
 * </p>
 * 
 * @author Igor A Tarasov me@dicr.dn.ua
 * @version 030113
 **********************************************************************************************************************/
public class DataNavFilterListModel extends AbstractListModel implements DataSetAware {
	private static final long serialVersionUID = 1L;

	protected List<Object> values = new ArrayList<Object>();

	protected DataSet dataset = null;

	protected String columnName = null;

	protected boolean ignoreDataSetEvents = false;

	protected DataListener dataListener = new DataListener();

	/*******************************************************************************************************************
	 * Конструктор
	 ******************************************************************************************************************/
	public DataNavFilterListModel() {
	// NOP
	}

	/*******************************************************************************************************************
	 * Обновляет модель данных
	 ******************************************************************************************************************/
	@SuppressWarnings("unchecked")
	protected void updateModel() {
		try {
			this.values = new ArrayList<Object>();
			if (this.dataset != null) {
				StorageDataSet storageds = this.dataset.getStorageDataSet();
				if (storageds != null) {
					if (!storageds.isOpen()) storageds.open();
					if (this.columnName != null && storageds.hasColumn(this.columnName) != null) {
						this.values = (List<Object>) DataMisc.getUniqColumnValues(storageds, this.columnName);
					}
				}
			}
			if (this.values == null) this.values = new Vector<Object>();
			if (this.values.size() > 0) this.values.add(0, "<Все>");
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this);
		} finally {
			fireContentsChanged(this, 0, 0);
		}
	}

	/*******************************************************************************************************************
	 * Возвращает размер списка
	 ******************************************************************************************************************/
	@Override
    public int getSize() {
		return this.values.size();
	}

	/*******************************************************************************************************************
	 * Возвращает заданный элемент
	 ******************************************************************************************************************/
	@Override
    public Object getElementAt(int index) {
		return this.values.get(index);
	}

	/*******************************************************************************************************************
	 * Возвращает источник данных
	 ******************************************************************************************************************/
	@Override
    public DataSet getDataSet() {
		return this.dataset;
	}

	/*******************************************************************************************************************
	 * Устанавливает источник данных
	 ******************************************************************************************************************/
	@Override
    public void setDataSet(DataSet theDataset) {
		if (this.dataset != theDataset) try {
			if (this.dataset != null) {
				StorageDataSet ds = this.dataset.getStorageDataSet();
				if (ds != null) {
					ds.removeAccessListener(this.dataListener);
					ds.removeDataChangeListener(this.dataListener);
				}
			}
			this.dataset = theDataset;
			if (theDataset != null) {
				RowFilterListener listener = theDataset.getRowFilterListener();
				if (listener == null) throw new NullPointerException("Необходимо установить RowFilterListener");
				if (!(listener instanceof DataSetFilter)) throw new IllegalStateException(
				        "RowFilterListener должен быть instanceof DataSetFilter");
				String[] columnNames = ((DataSetFilter) listener).getFilteredColumns();
				if (columnNames == null || columnNames.length < 1) throw new NullPointerException(
				        "DataSetFilter column name == null");
				this.columnName = columnNames[0];
				StorageDataSet ds = theDataset.getStorageDataSet();
				ds.addAccessListener(this.dataListener);
				ds.addDataChangeListener(this.dataListener);
				theDataset.open();
			}
		} finally {
			updateModel();
		}
	}

	/*******************************************************************************************************************
	 * ######################################################################### Слушатель данных
	 * #########################################################################
	 ******************************************************************************************************************/
	class DataListener extends DataChangeAdapter implements AccessListener {
		/***************************************************************************************************************
		 * Доступ к данным
		 **************************************************************************************************************/
		@Override
        public void accessChange(AccessEvent e) {
			try {
				DataNavFilterListModel.this.ignoreDataSetEvents = (e.getID() == AccessEvent.CLOSE);
			} catch (Exception ex) {
				DicrExceptionHandler.handleException(ex, this);
			} finally {
				updateModel();
			}
		}

		/***************************************************************************************************************
		 * Изменение данных
		 **************************************************************************************************************/
		@Override
		public void dataChanged(DataChangeEvent e) {
			if (!DataNavFilterListModel.this.ignoreDataSetEvents) {
				try {
					switch (e.getID()) {
						case DataChangeEvent.DATA_CHANGED:
						case DataChangeEvent.ROW_ADDED:
						case DataChangeEvent.ROW_CHANGE_POSTED:
						case DataChangeEvent.ROW_DELETED:
							updateModel();
					}
				} catch (Exception ex) {
					DicrExceptionHandler.handleException(ex, this);
				}
			}
		}
	}
}
